#include"../inc/EpollLoop.h"

namespace http_server
{
    EpollLoop::EpollLoop(Accept& aaccept)
    : _epfd(epollfdCreate()), _eventfd(eventfdCreate()), _events(1024), _accept(aaccept), _status(false)
    {
        addEvent(_accept.getFd());
        addEvent(_eventfd);
    }

    void EpollLoop::Loop()
    {
        if(_status)
            return;
        else
        {
            _status = true;
            epollWait();
        }
    }

    void EpollLoop::Stop()
    {
        if(_status)
            _status = false;
    }

    void EpollLoop::epollWait()
    {
            while(_status)
            {
                int nready = epoll_wait(_epfd, &*_events.begin(), _events.size(), 10000);
                if(-1 == nready && errno == EINTR)
                    continue;
                else if(-1 == nready)
                    perror("epoll_wait err");
                else if(_events.size() == nready)
                    _events.resize(_events.size() * 2);
                else 
                    for(int i = 0; i < nready; i++)
                    {
                        int fd = _events[i].data.fd;
                        if(_accept.getCfd() == fd)
                            addEvent(fd);
                    }
            }
    }

    int EpollLoop::epollfdCreate()
    {
        int epfd = epoll_create(1);
        if(-1 == epfd)
            perror("epoll_create err");
        return epfd;
    }

    int EpollLoop::eventfdCreate()
    {
        int ret = eventfd(0, 0);
        if(-1 == ret)
            perror("eventfd err");
        return ret;
    }

    void EpollLoop::addEvent(int fd)
    {
        epoll_event ev;
        ev.data.fd = fd;
        ev.events = EPOLLIN;
        int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &ev);
        if(-1 == ret)
            perror("epoll_ctl_add err");
    }

    void EpollLoop::delEvent(int fd)
    {
        epoll_event ev;
        ev.data.fd = fd;
        ev.events = EPOLLIN;
        int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, &ev);
        if(-1 == ret)
            perror("epoll_ctl_del err");
    }
}